/**************************************************************************************************
**                                                                                               **
**  文件名称:  app_pwrcheck.c                                                                    **
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2017                                     **
**  文件描述:  电源电压监测及检测模块                                                            **
**  ===========================================================================================  **
**  创建信息:  | 2017-8-3 | LEON | 创建本模块                                                    **
**  ===========================================================================================  **
**  修改信息:  单击此处添加....                                                                  **
**************************************************************************************************/
#include "app_include.h"
#include "app_pwrcheck.h"

/*************************************************************************************************/
/*                           模块宏                                                              */
/*************************************************************************************************/
#define PWRCHECK_SCAN        _SECOND, 1

#define VERIFY_RATIO_A       (157)                                             /* 电压校正系数A */
#define VERIFY_RATIO_B       (130)                                             /* 电压校正系数B */

#define PWRLOWHDL_MAX        5                                                 /* 欠压状态回调函数个数 */

#define CONFIRM_COUNT        10                                                /* 持续满足条件的时间 */

/*************************************************************************************************/
/*                           电压状态变化回调结构                                                */
/*************************************************************************************************/
typedef struct {
    PWR_STAT_E     pwrstt;                                                     /* 电压状态变化类型 */
    void         (*inform)(PWR_STAT_E);                                        /* 欠压状态变化回调函数 */
} PWRLOW_REG_T;

/*************************************************************************************************/
/*                           电压状态控制结构体                                                  */
/*************************************************************************************************/
typedef struct {
    BOOLEAN        islow;                                                      /* 是否处于欠压状态 */
    INT8U          count;                                                      /* 欠压状态确认计数器 */
    PWRLOW_REG_T   pcreg[PWRLOWHDL_MAX];                                       /* 电压状态变化通知函数 */
} PWRLOW_CTRL_T;

/*************************************************************************************************/
/*                           模块静态变量定义                                                    */
/*************************************************************************************************/
static INT8U          s_pwrchcktmr;
static INT32U         s_powervalue;                                            /* 当前的电源电压值 */
static PWR_RATIO_T    s_pwradratio;                                            /* 电压值计算系数 */
static BOOLEAN        s_12v_system;                                            /* 是否处于12V供电系统 */
static PWRLOW_CTRL_T  s_pwrlowctrl;                                            /* 欠压状态控制结构 */

/**************************************************************************************************
**  函数名称:  ExcutePwrStatInform
**  功能描述:  执行电压状态变化的通知函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void ExcutePwrStatInform(PWR_STAT_E type)
{
    INT8U i;
    
    for (i = 0; i < PWRLOWHDL_MAX; i++) {
        if ((s_pwrlowctrl.pcreg[i].pwrstt == type) || (s_pwrlowctrl.pcreg[i].pwrstt == PWR_STAT_BOTH)) {
            if (s_pwrlowctrl.pcreg[i].inform != NULL) {
                s_pwrlowctrl.pcreg[i].inform(type);
            }
        }
    }
}

/**************************************************************************************************
**  函数名称:  PowerStateCheck
**  功能描述:  检测是否存在欠压状态
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void PowerStateCheck(INT32U low, INT32U back)
{
    if (s_pwrlowctrl.islow == FALSE) {                                         /* 尚未触发欠压状态 */
        if (s_powervalue < low) {                                              /* 本次采集电压过低 */
            if (s_pwrlowctrl.count++ > CONFIRM_COUNT) {                        /* 欠压状态计数确认 */
                s_pwrlowctrl.islow = TRUE;
                s_pwrlowctrl.count = 0;
                ExcutePwrStatInform(PWR_STAT_LOW);
            }
        } else {                                                               /* 电源电压状态正常 */
            s_pwrlowctrl.count = 0;                                            /* 清零计数器 */
        }
    } else {                                                                   /* 已经处于欠压状态 */
        if (s_powervalue > back) {                                             /* 本次采集电压正常 */
            if (s_pwrlowctrl.count++ > CONFIRM_COUNT) {                        /* 恢复状态计数确认 */
                s_pwrlowctrl.islow = FALSE;
                s_pwrlowctrl.count = 0;
                ExcutePwrStatInform(PWR_STAT_BACK);
            }
        } else {                                                               /* 电源电压依然欠压 */
            s_pwrlowctrl.count = 0;                                            /* 清零计数器 */
        }
    }
}

/**************************************************************************************************
**  函数名称:  PwrCheckScanHdl
**  功能描述:  定时器处理函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void PwrCheckScanHdl(void)
{
    INT32S powerad;
    
    powerad = DAL_ADC_GetValue(ADC_CH_0);
    
    s_powervalue = powerad * s_pwradratio.ratio_a / 100 + s_pwradratio.ratio_b;/* 这个系数由硬件决定 */
    
    if (s_powervalue < DIVID_12V_24V) {                                        /* 识别12V系统还是24V系统 */
        if (s_12v_system == FALSE) {                                           /* 切换到12V系统的标记 */
            s_12v_system = TRUE;
            s_pwrlowctrl.count = 0;
            s_pwrlowctrl.islow = FALSE;
        } else {                                                               /* 已经处于12V系统的状态下 */
            PowerStateCheck(LOW_POWER_12V, BCK_POWER_12V);                     /* 进行12V系统欠压状态检测 */
        }
    } else {
        if (s_12v_system == TRUE) {                                            /* 切换到24V系统的标记 */
            s_12v_system = FALSE;
            s_pwrlowctrl.count = 0;
            s_pwrlowctrl.islow = FALSE;
        } else {                                                               /* 已经处于24V系统的状态下 */
            PowerStateCheck(LOW_POWER_24V, BCK_POWER_24V);                     /* 进行24V系统欠压状态检测 */
        }
    }
}

/**************************************************************************************************
**  函数名称:  PCParaChangeHdl
**  功能描述:  参数变更的回调通知函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void PCParaChangeHdl(INT16U ppid)
{
    PP_ReadItem(PP_PWRRATIO, &s_pwradratio);

    #if DEBUG_COMM > 0
    if (s_pwradratio.ratio_b >= 0) {
        Debug_SysPrint("Power_Value Formula Update: [y = %d * x + %d]\r\n", s_pwradratio.ratio_a, s_pwradratio.ratio_b);
    } else {
        Debug_SysPrint("Power_Value Formula Update: [y = %d * x - %d]\r\n", s_pwradratio.ratio_a, -s_pwradratio.ratio_b);
    }
    #endif
}

/**************************************************************************************************
**  函数名称:  PwrCheck_Init
**  功能描述:  模块初始化
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void PwrCheck_Init(void)
{
    s_12v_system = TRUE;
    
    memset((INT8U *)&s_pwrlowctrl, 0, sizeof(s_pwrlowctrl));
    
    if (PP_ReadItem(PP_PWRRATIO, &s_pwradratio) == FALSE) {                    /* 读取参数失败，则设置为缺省值 */
        s_pwradratio.ratio_a = VERIFY_RATIO_A;
        s_pwradratio.ratio_b = VERIFY_RATIO_B;
        PP_WriteItem(PP_PWRRATIO, &s_pwradratio, TRUE);
    }
    
    #if DEBUG_COMM > 0
    if (s_pwradratio.ratio_b >= 0) {
        Debug_SysPrint("Get Power_Value Formula: [y = %d * x + %d]\r\n", s_pwradratio.ratio_a, s_pwradratio.ratio_b);
    } else {
        Debug_SysPrint("Get Power_Value Formula: [y = %d * x - %d]\r\n", s_pwradratio.ratio_a, -s_pwradratio.ratio_b);
    }
    #endif
    
    SYS_ASSERT(PP_RegInformer(PP_PWRRATIO, PCParaChangeHdl) == TRUE, RETURN_VOID);
    
    s_pwrchcktmr = OSI_CreateTimer(PwrCheckScanHdl);
    OSI_StartTimer(s_pwrchcktmr, PWRCHECK_SCAN);
}

/**************************************************************************************************
**  函数名称:  GetSysPwrValue
**  功能描述:  获取系统电源电压值 [单位: 0.01V. eg: 填入1220表示实际电压为12.2V]
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32U GetSysPwrValue(void)
{
    return s_powervalue;
}

/**************************************************************************************************
**  函数名称:  GetSysPwrType
**  功能描述:  获取电源系统类型 [是否为12V系统]
**  输入参数:  无
**  输出参数:  无
**  返回参数:  12V系统返回TRUE，24V系统返回FALSE
**************************************************************************************************/
BOOLEAN GetSysPwrType(void)
{
    return s_12v_system;
}

/**************************************************************************************************
**  函数名称:  GetSysPwrLow
**  功能描述:  获取系统欠压状态
**  输入参数:  无
**  输出参数:  无
**  返回参数:  处于欠压状态下返回TRUE，否则返回FALSE
**************************************************************************************************/
BOOLEAN GetSysPwrLow(void)
{
    return s_pwrlowctrl.islow;
}

/**************************************************************************************************
**  函数名称:  RegPwrStatInform
**  功能描述:  注册系统电压状态变化的通知函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
BOOLEAN RegPwrStatInform(PWR_STAT_E type, void (*inform)(PWR_STAT_E))
{
    INT8U i;
    
    for (i = 0; i < PWRLOWHDL_MAX; i++) {                                      /* 寻找空闲的注册表 */
        if (s_pwrlowctrl.pcreg[i].inform == NULL) {
            break;
        }
    }
    
    SYS_ASSERT(i < PWRLOWHDL_MAX, RETURN_FALSE);
    
    s_pwrlowctrl.pcreg[i].pwrstt = type;
    s_pwrlowctrl.pcreg[i].inform = inform;
    
    return TRUE;
}


